package model

import (
	"sync"
	"time"
)

type CacheQueue struct {
	InChan  chan *Request
	OutChan chan *Request
	Cache   []*Request
	lock    sync.Mutex
	stop    bool
}

func (c *CacheQueue) Init(num int) {
	c.InChan = make(chan *Request, num)
	c.OutChan = make(chan *Request, num)
	c.Cache = make([]*Request, 0)
	c.stop = false
}

func (c *CacheQueue) Start() {
	go func() {
		for !c.stop {
			select {
			case req := <-c.InChan:
				select {
				case c.OutChan <- req:
				case <-time.After(time.Microsecond * 10):
					c.addCache(req)
				}
			case <-time.After(time.Microsecond * 9):
				if len(c.Cache) > 0 {
					c.cleanCache()
				}
				time.Sleep(time.Microsecond * 10)
			}
		}
	}()
}

func (c *CacheQueue) Stop() {
	c.stop = true
}

func (c *CacheQueue) cleanCache() {
	if len(c.Cache) > 0 {
		for _, r := range c.getCacheAndClean() {
			c.OutChan <- r
		}
	}
}

func (c *CacheQueue) getCacheAndClean() []*Request {
	c.lock.Lock()
	defer c.lock.Unlock()
	q := c.Cache
	c.Cache = make([]*Request, 0)
	return q
}

func (c *CacheQueue) addCache(req *Request) {
	c.lock.Lock()
	defer c.lock.Unlock()
	c.Cache = append(c.Cache, req)
}
